﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace GVPSys.control
{
    public class ExTextBox : TextBox
    {
        static ExTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ExTextBox), new FrameworkPropertyMetadata(typeof(ExTextBox)));
        }

        Image OperateImageE;
        Image TipImageE;
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var bord = VisualTreeHelper.GetChild(this, 0) as Border;
            Grid gr = bord.FindName("gdpassword") as Grid;
            TipImageE = gr.FindName("TipImage") as Image;
            OperateImageE = gr.FindName("OperateImage") as Image;

            //TipImageE.PreviewMouseLeftButtonUp +=TipImageE_PreviewMouseLeftButtonUp;
            OperateImageE.PreviewMouseLeftButtonUp += OperateImageE_PreviewMouseLeftButtonUp;


        }

        private void OperateImageE_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Text = "";
        }


        //3.定义依赖属性　
        public static DependencyProperty WaterRemarkProperty =
            DependencyProperty.Register("WaterRemark", typeof(string), typeof(ExTextBox));

        /// <summary>
        /// 水印文字
        /// </summary>
        public string WaterRemark
        {
            get { return GetValue(WaterRemarkProperty).ToString(); }
            set { SetValue(WaterRemarkProperty, value); }
        }

        public static DependencyProperty BorderCornerRadiusProperty =
            DependencyProperty.Register("BorderCornerRadius", typeof(CornerRadius), typeof(ExTextBox));

        /// <summary>
        /// 边框角度
        /// </summary>
        public CornerRadius BorderCornerRadius
        {
            get { return (CornerRadius)GetValue(BorderCornerRadiusProperty); }
            set { SetValue(BorderCornerRadiusProperty, value); }
        }

        public static DependencyProperty IsPasswordBoxProperty =
            DependencyProperty.Register("IsPasswordBox", typeof(bool), typeof(ExTextBox), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsPasswordBoxChnage)));

        /// <summary>
        /// 是否为密码框
        /// </summary>
        public bool IsPasswordBox
        {
            get { return (bool)GetValue(IsPasswordBoxProperty); }
            set { SetValue(IsPasswordBoxProperty, value); }
        }

        public static DependencyProperty PasswordCharProperty =
            DependencyProperty.Register("PasswordChar", typeof(char), typeof(ExTextBox), new FrameworkPropertyMetadata('●'));

        /// <summary>
        /// 替换明文的单个密码字符
        /// </summary>
        public char PasswordChar
        {
            get { return (char)GetValue(PasswordCharProperty); }
            set { SetValue(PasswordCharProperty, value); }
        }

        public static DependencyProperty PasswordStrProperty =
            DependencyProperty.Register("PasswordStr", typeof(string), typeof(ExTextBox), new FrameworkPropertyMetadata(string.Empty));
        /// <summary>
        /// 密码字符串
        /// </summary>
        public string PasswordStr
        {
            get { return GetValue(PasswordStrProperty).ToString(); }
            set { SetValue(PasswordStrProperty, value); }
        }

        /// <summary>
        /// 图标大小
        /// </summary>
        public double ImageSize
        {
            get { return (double)GetValue(ImageSizeProperty); }
            set { SetValue(ImageSizeProperty, value); }
        }

        public static readonly DependencyProperty ImageSizeProperty =
            DependencyProperty.Register("ImageSize", typeof(double), typeof(ExTextBox),
            new FrameworkPropertyMetadata(26.0, FrameworkPropertyMetadataOptions.AffectsRender));

        public static readonly DependencyProperty TipImageProperty = DependencyProperty.Register(
              "TipImage",
              typeof(string),
              typeof(ExTextBox),
              new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));

        /// <summary>
        /// 
        /// <summary>
        public string TipImage
        {
            get { return (string)GetValue(TipImageProperty); }
            set { SetValue(TipImageProperty, value); }
        }

        public static readonly DependencyProperty OperateImageProperty = DependencyProperty.Register(
                      "OperateImage",
                      typeof(string),
                      typeof(ExTextBox),
                      new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));

        /// <summary>
        /// 
        /// <summary>
        public string OperateImage
        {
            get { return (string)GetValue(OperateImageProperty); }
            set { SetValue(OperateImageProperty, value); }
        }

        public static readonly DependencyProperty TipImageHideProperty = DependencyProperty.Register(
              "TipImageHide",
              typeof(Visibility),
              typeof(ExTextBox),
              new FrameworkPropertyMetadata(Visibility.Collapsed));

        /// <summary>
        /// 
        /// <summary>
        public Visibility TipImageHide
        {
            get { return (Visibility)GetValue(TipImageHideProperty); }
            set { SetValue(TipImageHideProperty, value); }
        }

        public static readonly DependencyProperty OperateHideProperty = DependencyProperty.Register(
                      "OperateHide",
                      typeof(Visibility),
                      typeof(ExTextBox),
                      new FrameworkPropertyMetadata(Visibility.Collapsed));

        /// <summary>
        /// 
        /// <summary>
        public Visibility OperateHide
        {
            get { return (Visibility)GetValue(OperateHideProperty); }
            set { SetValue(OperateHideProperty, value); }
        }



        //依赖属性发生改变时候触发
        private static void ImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Application.GetResourceStream(new Uri((string)e.NewValue));
            if (e.Property.Name == "TipImage")
            {
                (sender as ExTextBox).TextBox_Changed(0);
            }

            if (e.Property.Name == "OperateImage")
            {
                (sender as ExTextBox).TextBox_Changed(1);
            }

        }

        private void TextBox_Changed(int index)
        {
            if (index == 0)
                TipImageHide = Visibility.Visible;
            else
                OperateHide = Visibility.Visible;
        }

        //4.当设置为密码框时，监听TextChange事件，处理Text的变化，这是密码框的核心功能
        private static void OnIsPasswordBoxChnage(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ExTextBox).SetEvent();
        }

        /// <summary>
        /// 定义TextChange事件
        /// </summary>
        private void SetEvent()
        {
            if (IsPasswordBox)
                this.TextChanged += TextBox_TextChanged;
            else
                this.TextChanged -= TextBox_TextChanged;
        }
        //5.在TextChange事件中，处理Text为密码文，并将原字符记录给PasswordStr予以存储
        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!IsResponseChange) //响应事件标识，替换字符时，不处理后续逻辑
                return;
            //Console.WriteLine(string.Format("------{0}------", e.Changes.Count));
            foreach (TextChange c in e.Changes)
            {
                //Console.WriteLine(string.Format("addLength:{0} removeLenth:{1} offSet:{2}", c.AddedLength, c.RemovedLength, c.Offset));
                PasswordStr = PasswordStr.Remove(c.Offset, c.RemovedLength); //从密码文中根据本次Change对象的索引和长度删除对应个数的字符
                PasswordStr = PasswordStr.Insert(c.Offset, Text.Substring(c.Offset, c.AddedLength));   //将Text新增的部分记录给密码文
                lastOffset = c.Offset;
            }
            //Console.WriteLine(PasswordStr);
            /*将文本转换为密码字符*/
            IsResponseChange = false;  //设置响应标识为不响应
            this.Text = ConvertToPasswordChar(Text.Length);  //将输入的字符替换为密码字符
            IsResponseChange = true;   //回复响应标识
            this.SelectionStart = lastOffset + 1; //设置光标索引
            //Console.WriteLine(string.Format("SelectionStar:{0}", this.SelectionStart));
        }



        /// <summary>
        /// 按照指定的长度生成密码字符
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private string ConvertToPasswordChar(int length)
        {
            if (PasswordBuilder != null)
                PasswordBuilder.Clear();
            else
                PasswordBuilder = new StringBuilder();
            for (var i = 0; i < length; i++)
                PasswordBuilder.Append(PasswordChar);
            return PasswordBuilder.ToString();
        }

        //6.如果用户设置了记住密码，密码文(PasswordStr)一开始就有值的话，别忘了在Load事件里事先替换一次明文
        private void ExTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            if (IsPasswordBox)
            {
                IsResponseChange = false;
                this.Text = ConvertToPasswordChar(PasswordStr.Length);
                IsResponseChange = true;
            }
        }

        private bool IsResponseChange = true;
        private StringBuilder PasswordBuilder;
        private int lastOffset = 0;
    }
}
